import { Component, EventEmitter, HostBinding, NgZone, OnInit, Output, TemplateRef, ViewChild } from '@angular/core';
import { cloneDeep } from 'lodash-es';
import { TreeTableComponent } from '@farris/ui-treetable';
import { NotifyService } from '@farris/ui-notify';
import { DomService, FormSchemaEntity, FormSchemaEntityField, SchemaService, FormBindingType, FormComponent, FormViewModel } from '@farris/designer-services';
import { ControlService } from '../../../../../../service/control.service';
import { Subject } from 'rxjs';
import { HttpClient } from '@angular/common/http';
import { DgControl } from '../../../../../../utils/dg-control';
import { TableFillInFormTempalteService } from './services/table-fillin-template.service';

/**
 * 动态面板构造类
 */
export class DynamicAreaItemBuildInfo {
    dynamicItem: any;
    components?: FormComponent[];
    viewModels?: FormViewModel[];
}

/**
 * 预制的组件模板结构
 */
export class DynamicTemplateJson {
    id: string;
    title: string;

    /** 模板内容 */
    contents: any[];

    /** 模板中涉及的子组件 */
    components?: FormComponent[];
}

/**
 * 动态面板新增窗口
 */
@Component({
    selector: 'app-create-dynamic-item',
    templateUrl: './create-dynamic-item.component.html',
    styleUrls: ['./create-dynamic-item.component.css'],
    providers: [TableFillInFormTempalteService]
})
export class CreateDynamicItemComponent implements OnInit {

    @Output() save = new EventEmitter<any>();

    @Output() cancel = new EventEmitter<any>();

    @HostBinding('class')
    cls = 'd-flex f-utils-fill-flex-column h-100';

    @ViewChild('btns') btns: TemplateRef<any>;

    /** 步骤条数据  */
    stepMessages = [];
    /** 当前选中步骤id */
    currentStepId = 'selectTemplates';
    /** 当前选中步骤索引 */
    activeStepIndex = 0;

    /** 当前表单schema实体 */
    schemaEntity;

    /** 实体树表数据源 */
    schemaSource = [];
    /** 实体树表列配置 */
    schemaTreeColumns = [{ field: 'name', title: '名称' }];
    /**  选中的实体表 */
    selectedEntity: FormSchemaEntity;
    /** 选中的表节点（树节点） */
    selectedEntityTreeNode;
    /** 是否选中主表 */
    isSelectMainTable = false;
    /** 主实体label */
    mainEntityLabel: string;
    // 实体树表实例
    @ViewChild('schemaTree') schemaTree: TreeTableComponent;

    /** 系统预制的组件模板列表 */
    componentTemplates: any[];
    /** 选中的模板 */
    selectedTemplate: any;
    /** 选中模板的JSON结构 */
    selectedTempalteJson: DynamicTemplateJson;


    /** 展示字段树表实例 */
    @ViewChild('fieldsTree') fieldsTree: TreeTableComponent;
    /** 展示字段树表数据源 */
    fieldsSource = [];
    /** 展示字段树表列配置 */
    filedsTreeColumns = [
        { field: 'name', title: '字段名称' }, { field: 'bindingField', title: '绑定字段' },
        { field: 'type', title: '字段类型', width: 100 }, { field: 'show', title: '显示', width: 120 }
    ];
    /** 是否全选字段 */
    selectedAllFields = false;
    /** 字段勾选配置 */
    selected = {};
    /** 选中的字段 */
    selectedFields = [];

    /** 组件的构造信息 */
    buildInfo: DynamicAreaItemBuildInfo = null;

    /** 表单中已添加的字段集合，用于添加组件时排除掉页面中同类型组件中已有的字段 */
    displayedFieldsMap = new Map<string, boolean>();

    /** 选中的实体下是否包含可勾选的字段，用于没有可选字段时不显示全选按钮 */
    hasSelectableFields = false;

    constructor(
        private notifyService: NotifyService,
        private domServ: DomService,
        private controlServ: ControlService,
        private schemServ: SchemaService,
        private http: HttpClient,
        private tableFillInService: TableFillInFormTempalteService,
        private ngZone: NgZone) { }

    ngOnInit() {
        this.initProgressData();
        // 现有的schema实体
        const entityOrigin = this.schemServ.getSchemaEntities();
        this.schemaEntity = cloneDeep(entityOrigin);

        this.assembleSchemaSource();

        this.getComponentTemplates();
        this.selectedTemplate = null;
    }


    /**
     * 步骤条信息
     */
    private initProgressData() {
        this.stepMessages = [
            {
                id: 'selectTemplates',
                title: '选择组件模板'
            },
            {
                id: 'selectTable',
                title: '选择实体'
            },
            {
                id: 'selectShowFields',
                title: '选择字段'
            }
        ];

    }
    /**
     * 组装实体树
     */
    assembleSchemaSource() {
        const schemaTree = this.assembleSchemaBasicInfo2Tree(this.schemaEntity[0], 1);
        this.schemaSource = [schemaTree];
        this.ngZone.runOutsideAngular(() => {
            setTimeout(() => {
                this.schemaTree.selectNode(schemaTree.data.id);
            });
        });
    }

    /**
     * 将schema实体组装成树
     * 规则： 卡片类型组件只能选择主表，列表类型组件只能选择从表
     */
    private assembleSchemaBasicInfo2Tree(schemaEntity: FormSchemaEntity, level: number) {
        const result = {
            data: schemaEntity,
            expanded: true,
            children: [],
            selectable: true
        };

        if (schemaEntity.type.entities && schemaEntity.type.entities.length) {
            const childTable = schemaEntity.type.entities.map(ele => this.assembleSchemaBasicInfo2Tree(ele, level + 1));
            result.children = result.children.concat(childTable);
        }

        return result;
    }

    /**
     * 切换选中的实体节点
     */
    selectedEntityChanged(selectedEntityNode: any) {

        this.selectedEntityTreeNode = selectedEntityNode.node;
        this.isSelectMainTable = !selectedEntityNode.node.parent;
    }
    /**
     * 上一步
     */
    clickPreStep() {
        this.activeStepIndex = this.activeStepIndex - 1;
        this.currentStepId = this.stepMessages[this.activeStepIndex].id;
    }

    /**
     * 下一步
     */
    clickNextStep() {
        switch (this.currentStepId) {
            case 'selectTemplates': {
                if (!this.selectedTemplate) {
                    this.notifyService.warning('请先选择组件模板');
                    return;
                }
                this.getSelectedTemplateJson().subscribe(() => {
                    this.goToNextSetp();
                })
                break;
            }
            case 'selectTable': {
                if (!this.schemaTree.selectedRow) {
                    this.notifyService.warning('请先选择实体');
                    return;
                }
                // 获取选中实体
                this.selectedEntity = this.schemaTree.selectedRow.data;

                // 获取表单中已有的字段控件
                this.displayedFieldsMap.clear();
                this.getDisplayedFieldsMapBySelectedEntity();
                this.hasSelectableFields = false;

                // 组装字段树列表
                const fields = this.selectedEntity.type.fields;
                this.fieldsSource = this.assembleFields2Tree(fields, true);

                this.goToNextSetp();
                break;
            }
        }

    }
    private goToNextSetp() {
        this.activeStepIndex = this.activeStepIndex + 1;
        this.currentStepId = this.stepMessages[this.activeStepIndex].id;
    }
    /**
     * schema字段集合组装成树
     * @param fields schema字段集合
     */
    private assembleFields2Tree(fields: FormSchemaEntityField[], expandRelateNode = true) {
        const treeData = [];
        fields.forEach(element => {
            // 关联表字段 / UDT字段
            let children = [];
            if (element.type && element.type.fields && element.type.fields.length > 0) {
                children = this.assembleFields2Tree(element.type.fields, true);
            }
            const selectable = this.displayedFieldsMap ?
                children.length === 0 && !this.displayedFieldsMap.has(element.id) : children.length === 0;

            if (selectable) {
                this.hasSelectableFields = true;
            }

            treeData.push({
                data: element,
                children,
                expanded: expandRelateNode,
                selectable
            });
        });
        return treeData;
    }

    /**
     * 获取指定实体中已在当前表单中被占用的字段，场景：创建卡片组件时将已在其他组件中添加的字段排除掉
     */
    private getDisplayedFieldsMapBySelectedEntity() {
        if (!this.selectedEntity) {
            this.displayedFieldsMap.clear();
            return;
        }
        let targetComponentType = null;
        if (this.selectedTempalteJson && this.selectedTempalteJson.components && this.selectedTempalteJson.components.length > 0) {
            targetComponentType = this.selectedTempalteJson.components[0].componentType;
        }
        this.domServ.viewmodels.forEach(viewModel => {
            if (!viewModel.fields || viewModel.fields.length === 0) {
                return;
            }
            const componentNode = this.domServ.getComponentByVMId(viewModel.id);
            // 绑定同一个实体，并且是同类型的组件（form类、dataGrid类...）
            if (componentNode.componentType !== targetComponentType) {
                return;
            }
            const entityInfo = this.schemServ.getTableInfoByViewModelId(viewModel.id);
            if (entityInfo.id === this.selectedEntity.id) {
                viewModel.fields.forEach(field => {
                    this.displayedFieldsMap.set(field.id, true);
                });
            }
        });

    }
    /**
     * 获取模板列表
     * @param type 控件类型
     */
    private getComponentTemplates() {

        this.http.get<any[]>('assets/form/component-template/component-templates.json').subscribe(data => {
            if (data) {
                this.componentTemplates = cloneDeep(data);
            }
        });
    }

    /**
     * 获取模板列表
     * @param type 控件类型
     */
    private getSelectedTemplateJson(): Subject<any> {
        const subject = new Subject<any>();

        this.http.get<DynamicTemplateJson>(this.selectedTemplate.domJson).subscribe(data => {
            if (data) {
                this.selectedTempalteJson = data;
                subject.next();
            } else {
                this.notifyService.warning('组件模板不存在！');
                return;
            }
        });
        return subject;
    }

    changeSelectedTemplate(template: any) {
        this.selectedTemplate = template;
    }
    /**
     * 取消
     */
    clickCancel() {
        this.cancel.emit();
    }

    /**
     * 触发保存
     */
    clickSave() {
        if (!this.selectedTemplate) {
            this.notifyService.warning('请先选择组件模板');
            return;
        }

        if (this.selectedFields.length === 0) {
            this.notifyService.warning('请先选择字段');
            return;
        }

        // this.http.get<any[]>(this.selectedTemplate.domJson).subscribe(data => {
        //     if (data) {
        //         this.selectedTempalteJson = data;
        this.createDynamicItem();

        this.save.emit(this.buildInfo);
        // } else {
        //     this.notifyService.warning('组件模板不存在！');
        //     return;
        // }
        // });

    }


    private createDynamicItem() {
        const idSuffix = Math.random().toString(36).slice(2, 6);
        this.buildInfo = new DynamicAreaItemBuildInfo();

        const dynamicItemMetadata = this.controlServ.getControlMetaData(DgControl.DynamicAreaItem.type);
        dynamicItemMetadata.id = 'dynamicItem' + '_' + idSuffix;
        dynamicItemMetadata.title = this.selectedEntity.type.displayName;

        this.resolveContentsInTemplate();

        // 为了防止导入模板后ID重复，重置控件ID
        this.resetTemplateControlId(this.selectedTempalteJson.contents, idSuffix);
        if (this.selectedTempalteJson.components) {
            this.resetTemplateControlId(this.selectedTempalteJson.components, idSuffix);
        }

        // 将模板内容添加到动态面板下
        dynamicItemMetadata.contents = this.selectedTempalteJson.contents;
        this.buildInfo.dynamicItem = dynamicItemMetadata;

        // 若模板中包含子组件，则需要为子组件创建视图模型
        if (this.selectedTempalteJson.components) {
            const viewModels = [];
            this.selectedTempalteJson.components.forEach(c => {
                const viewModel = this.addViewModel(c);
                viewModels.push(viewModel);
            });

            this.buildInfo.viewModels = viewModels;
            this.buildInfo.components = this.selectedTempalteJson.components;
        }

        // 为控件增加命令绑定
        this.addCommandsToControl(this.selectedTempalteJson.components);

    }
    /**
     * 为控件绑定命令，需要根据模板区分
     */
    private addCommandsToControl(components: FormComponent[]) {
        switch (this.selectedTempalteJson.id) {
            case 'table-batch-fill-in-component': {
                this.tableFillInService.addCommandsToTableBatchComponent(components[0].viewModel);
                break;
            }
        }
    }
    /**
     * 修改basicFormViewModel，添加字段，默认无分组
     */
    private addViewModel(component: any) {
        const viewModel = new FormViewModel();
        viewModel.id = viewModel.code = component.viewModel;
        viewModel.name = this.selectedEntity.type.displayName || this.selectedEntity.type.name;

        viewModel.bindTo = this.getEntityInfoDataSource(this.schemaEntity);
        viewModel.parent = 'root-viewmodel';
        viewModel.commands = [];

        // 将字段添加到视图模型
        viewModel.fields = [];
        viewModel.states = [];
        viewModel.enableValidation = true;
        this.selectedFields.forEach(element => {
            viewModel.fields.push({
                type: FormBindingType.Form,
                id: element.id,
                fieldName: element.bindingField,
                groupId: null,
                groupName: null
            });
        });

        // 为模型添加命令，需要根据模板区分
        switch (this.selectedTempalteJson.id) {
            case 'table-batch-fill-in-component': {
                this.tableFillInService.addCommandsToTableViewModel(component, viewModel);
                break;
            }
        }

        // 为模型增加状态机
        const stateMachines = this.domServ.module.stateMachines;
        if (stateMachines && stateMachines.length) {
            viewModel.stateMachine = stateMachines[0].id;
        }

        return viewModel;
    }
    /**
     * 根据实体label获取用于viewModel的bindTo属性
     */
    private getEntityInfoDataSource(entities: FormSchemaEntity[], labelPath = ''): any {
        if (!entities || entities.length === 0) {
            return;
        }

        const parentLabelPath = labelPath;
        for (const entity of entities) {
            const entityType = entity.type;
            labelPath = parentLabelPath === '' ? entity.label : parentLabelPath + '/' + entity.label;

            this.mainEntityLabel = !this.mainEntityLabel ? entity.label : this.mainEntityLabel;

            if (this.selectedEntity.label === entity.label) {
                const bindTo = labelPath.replace(this.mainEntityLabel, '');
                return bindTo === '' ? '/' : bindTo;
            }
            if (entityType.entities && entityType.entities.length > 0) {
                const bindTo = this.getEntityInfoDataSource(entityType.entities, labelPath);
                if (bindTo) {
                    return bindTo;
                }
            }
        }
    }
    /**
     * 重置控件id
     * @param contents 
     * @param idSuffix 
     */
    private resetTemplateControlId(contents: any[], idSuffix: string) {
        contents.forEach(c => {
            if (c.type === DgControl.ComponentRef.type) {
                c.component = this.selectedEntity.label + '-' + idSuffix + '-component';
            }
            if (c.type === DgControl.Component.type) {
                c.id = this.selectedEntity.label + '-' + idSuffix + '-component';
                c.viewModel = this.selectedEntity.label + '-' + idSuffix + '-viewmodel';
            } else {
                c.id = c.id + '-' + idSuffix;
            }
            if (c.contents) {
                this.resetTemplateControlId(c.contents, idSuffix);
            }
            if (c.type === DgControl.Table.type && c.rows) {
                c.rows.forEach(row => {
                    if (row.columns) {
                        this.resetTemplateControlId(row.columns, idSuffix);
                    }
                });

            }

        });
    }


    private resolveContentsInTemplate() {
        switch (this.selectedTemplate.id) {
            case 'table-fill-in-component': case 'table-batch-fill-in-component': {
                this.tableFillInService.resolveTemplate(this.selectedTempalteJson, this.selectedEntity, this.selectedFields);
                break;
            }
        }
    }

    clickSelectAllFieldsCheckbox() {
        this.selectedFields = [];
        this.selectAllChange(this.fieldsSource);

    }

    selectAllChange(fieldsSource) {
        if (fieldsSource.length === 0) {
            return;
        }
        fieldsSource.forEach(fieldTreeNode => {
            const bindingField = fieldTreeNode.data.bindingField;
            if (fieldTreeNode.children && fieldTreeNode.children.length > 0) {
                this.selectAllChange(fieldTreeNode.children);
            } else {
                if (fieldTreeNode.selectable) {
                    this.selected[bindingField] = this.selectedAllFields;
                    if (this.selectedAllFields) {
                        this.selectedFields.push(fieldTreeNode.data);
                    }
                }

            }
        });
    }

    clickCheckbox(flag: boolean, rowData: any) {
        if (flag) {
            this.selectedFields.push(rowData);
            const fieldCheckboxCount = this.fieldsTree.el.nativeElement.getElementsByClassName('k-checkbox').length - 1;
            if (this.selectedFields.length === fieldCheckboxCount) {
                this.selectedAllFields = true;
            }
        } else {
            this.selectedFields = this.selectedFields.filter(f => f.bindingField !== rowData.bindingField);
            this.selectedAllFields = false;
        }
    }
}


